<?php

namespace Components\Utils\Funcs;

use Components\Utils\Funcs\Enum\PathStyle;

/**
 * 文件系统辅助函数
 * @author vijay
 */
class FileSystemHelper
{
    /**
     * 递归删除一个目录
     * @param string $dirPath 目录地址
     * @param bool $fileDelete 如果传入的是文件而非目录，是否也要删除
     * @return bool 是否成功删除
     */
    public static function deleteDir(string $dirPath, bool $fileDelete = true): bool
    {
        if (!is_dir($dirPath)) {
            if ($fileDelete && file_exists($dirPath)) {
                unlink($dirPath);
            }
            return !file_exists($dirPath);
        }
        $stack = [realpath($dirPath)];
        while ($stack) {
            $dir = array_pop($stack);
            $hasChildDir = false;
            $handle = opendir($dir);
            for ($child = readdir($handle); $child; $child = readdir($handle)) {
                if ($child == "." || $child == "..") {
                    continue;
                }
                $fullChild = "{$dir}/{$child}";
                if (is_dir($fullChild)) {
                    if (!$hasChildDir) {
                        $hasChildDir = true;
                        $stack[] = $dir;
                    }
                    $stack[] = $fullChild;
                } else {
                    unlink($fullChild);
                }
            }
            closedir($handle);
            if (!$hasChildDir) {
                rmdir($dir);
            }
        }
        return !file_exists($dirPath);
    }

    /**
     * 判断给定路径是否绝对路径
     * @param string $path 给定的文件路径
     * @return bool 给定路径是否绝对路径
     */
    public static function isAbsolutePath(string $path): bool
    {
        $pathStyle = self::pathStyle();
        switch ($pathStyle->getValue()) {
            case PathStyle::WINDOWS_STYLE:
                return strlen($path) >= 2 && $path[1] == ":"
                    && ($path[0] >= "A" && $path[0] <= "Z" || $path[0] >= "a" && $path[0] <= "z");
            default:
                return strlen($path) >= 1 && $path[0] == "/";
        }
    }

    /**
     * @return PathStyle 当前系统的路径风格
     */
    public static function pathStyle(): PathStyle
    {
        $curPath = __FILE__;
        if ($curPath[0] == "/") {
            return PathStyle::UNIX_STYLE();
        } else {
            return PathStyle::WINDOWS_STYLE();
        }
    }

    /**
     * 创建一个文件
     * @param string $fileName 文件路径
     * @return bool 文件是否创建成功
     */
    public static function touchFile(string $fileName): bool
    {
        if (file_exists($fileName)) {
            return !is_dir($fileName);
        }
        if (self::pathStyle()->getValue() == PathStyle::WINDOWS_STYLE) {
            $fileName = str_replace("\\", "/", $fileName);
        }
        $pos = strrpos($fileName, "/");
        if ($pos !== false && !self::mkdir(substr($fileName, 0, $pos), 0777, true)) {
            return false;
        }
        return touch($fileName);
    }

    /**
     * 创建一个目录
     * @param string $pathname 目录名
     * @param int $mode 权限
     * @param bool $recursive 是否递归
     * @return bool 目录是否创建成功
     */
    public static function mkdir(string $pathname, int $mode = 0777, bool $recursive = false): bool
    {
        return file_exists($pathname) ? is_dir($pathname) : mkdir($pathname, $mode, $recursive);
    }
}

# end of file
